﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Workflow.ComponentModel;
using System.Workflow.Runtime.Hosting;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Web;

namespace LocalEvents.Business
{
    public class WorkflowHelper
    {
        public static WorkflowRuntime Start()
        {
            WorkflowRuntime workflowRuntime;

            if (HttpContext.Current == null)
                workflowRuntime = new WorkflowRuntime();
            else
            {
                if (HttpContext.Current.Application["WorkflowRuntime"] == null)
                    workflowRuntime = new WorkflowRuntime();
                else
                    return HttpContext.Current.Application["WorkflowRuntime"] as WorkflowRuntime;
            }

            var scheduler = new ManualWorkflowSchedulerService();
            workflowRuntime.AddService(scheduler);

            workflowRuntime.StartRuntime();

            if (null != HttpContext.Current)
                HttpContext.Current.Application["WorkflowRuntime"] = workflowRuntime;

            return workflowRuntime;
        }

        public static void Stop()
        {
            WorkflowRuntime workflowRuntime = HttpContext.Current.Application["WorkflowRuntime"] as System.Workflow.Runtime.WorkflowRuntime;
            workflowRuntime.StopRuntime();
            HttpContext.Current.Application.Remove("WorkflowRuntime");
        }

        public static void ExecuteWorkflow(Type workflowType, Dictionary<string, object> properties)
        {
            properties.Add("TheContext", HttpContext.Current);

            var workflowRuntime = Start();
            var scheduler = workflowRuntime.GetService<ManualWorkflowSchedulerService>();
            WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowType, properties);
            instance.Start();

            EventHandler<WorkflowCompletedEventArgs> completedHandler = null;
            completedHandler = delegate(object o, WorkflowCompletedEventArgs e)
            {
                if (e.WorkflowInstance.InstanceId == instance.InstanceId)
                {
                    workflowRuntime.WorkflowCompleted -= completedHandler;

                    Dictionary<string, object>.Enumerator enumerator = e.OutputParameters.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        KeyValuePair<string, object> pair = enumerator.Current;
                        if (properties.ContainsKey(pair.Key))
                        {
                            properties[pair.Key] = pair.Value;
                        }
                    }
                }
            };

            Exception workflowException = null;

            EventHandler<WorkflowTerminatedEventArgs> terminatedHandler = null;
            terminatedHandler = delegate(object o, WorkflowTerminatedEventArgs e)
            {
                if (e.WorkflowInstance.InstanceId == instance.InstanceId)
                {
                    workflowRuntime.WorkflowTerminated -= terminatedHandler;
                    workflowException = e.Exception;
                }
            };

            workflowRuntime.WorkflowCompleted += completedHandler;
            workflowRuntime.WorkflowTerminated += terminatedHandler;

            scheduler.RunWorkflow(instance.InstanceId);

            if (workflowException != null)
            {
                // TODO: Log 
                throw workflowException;
            }
        }
    }
}
